home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
PaintUndo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
6KB
|
258 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
#include <X11/IntrinsicP.h>
#include "xpaint.h"
#include "misc.h"
#include "PaintP.h"
#define GET_PW(w) ((PaintWidget)(((PaintWidget)w)->paint.paint == None ? w : ((PaintWidget)w)->paint.paint))
void UndoSwap(Widget w)
{
PaintWidget pw = GET_PW(w);
/*
** No undo buffers
*/
if (pw->paint.head == NULL)
return;
/*
** Walked off the end of the undo buffers.
*/
if (pw->paint.undo == NULL) {
for (pw->paint.undo = pw->paint.head;
pw->paint.undo != NULL && !pw->paint.undo->valid;
pw->paint.undo = pw->paint.undo->prev);
} else {
pw->paint.undo = pw->paint.undo->prev;
}
PwUpdate(w, NULL, True);
}
/*
**
** Consider the undo system...
**
** UndoBuffer
**
** 0 1 2 3
**
** ^ ^-- pw->paint.undo
** + pw->paint.top (base reference)
**
*/
Pixmap PwUndoStart(Widget w, XRectangle *rect)
{
PaintWidget pw = GET_PW(w);
UndoStack *cur, *nxt, *start;
pw->paint.dirty = True;
/*
** If there are no undo buffers
*/
if (pw->paint.head == NULL)
return pw->paint.base;
/*
** If we are in the middle, and need to start writing.
** it means that we've been doing some undo, and thus
** the next stuff in line is invalid.
*/
cur = pw->paint.undo;
if (cur != pw->paint.head) {
if (cur == NULL)
cur = pw->paint.tail;
for (; cur != NULL; cur = cur->next)
cur->valid = False;
if (pw->paint.undo == NULL) {
nxt = pw->paint.tail;
} else {
nxt = pw->paint.undo->next;
}
start = NULL;
} else if (cur->valid) {
/*
** If the current is valid, then everthing behind it must be as well
** therfor tail must be valid.
*/
nxt = pw->paint.tail;
XCopyArea(XtDisplay(pw), nxt->pixmap, pw->paint.base,
pw->paint.gc,
nxt->box.x, nxt->box.y,
nxt->box.width, nxt->box.height,
nxt->box.x, nxt->box.y);
/*
** Unlink the tail, and move it to the front.
*/
if (pw->paint.head != pw->paint.tail) {
if (nxt->next != NULL)
nxt->next->prev = NULL;
pw->paint.tail = nxt->next;
pw->paint.head->next = nxt;
nxt->next = NULL;
nxt->prev = pw->paint.head;
pw->paint.head = nxt;
start = pw->paint.tail;
} else {
start = nxt;
}
}
if (start == NULL) {
/*
** Nothing valid, copy the whole thing
*/
XCopyArea(XtDisplay(pw), pw->paint.base, nxt->pixmap,
pw->paint.gc,
0, 0,
pw->paint.drawWidth, pw->paint.drawHeight,
0, 0);
} else {
for (cur = start; cur != pw->paint.head; cur = cur->next) {
XCopyArea(XtDisplay(pw), cur->pixmap, nxt->pixmap,
pw->paint.gc,
cur->box.x, cur->box.y,
cur->box.width, cur->box.height,
cur->box.x, cur->box.y);
}
}
if (rect == NULL) {
nxt->box.x = 0;
nxt->box.y = 0;
nxt->box.width = 0;
nxt->box.height = 0;
} else {
nxt->box = *rect;
}
nxt->valid = True;
pw->paint.undo = nxt;
return nxt->pixmap;
}
void UndoStart(Widget w, OpInfo *info)
{
if (info->surface != opPixmap)
return;
info->drawable = PwUndoStart(w, NULL);
}
void UndoStartPoint(Widget w, OpInfo *info, int x, int y)
{
PaintWidget pw = GET_PW(w);
if (info->surface != opPixmap)
return;
UndoStart(w, info);
if (pw->paint.undo == NULL)
return;
pw->paint.undo->box.x = x - pw->paint.lineWidth;
pw->paint.undo->box.y = y - pw->paint.lineWidth;
pw->paint.undo->box.width = 1 + pw->paint.lineWidth * 2;
pw->paint.undo->box.height = 1 + pw->paint.lineWidth * 2;
}
void UndoGrow(Widget w, int x, int y)
{
PaintWidget pw = GET_PW(w);
XRectangle *rect;
int dx, dy;
if (pw->paint.undo == NULL)
return;
rect = &pw->paint.undo->box;
rect->x += pw->paint.lineWidth;
rect->y += pw->paint.lineWidth;
rect->width -= pw->paint.lineWidth * 2;
rect->height-= pw->paint.lineWidth * 2;
dx = x - rect->x;
dy = y - rect->y;
if (dx > 0) {
rect->width = MAX(rect->width, dx);
} else {
rect->width = (int)rect->width - dx + 1;
rect->x = x;
}
if (dy > 0) {
rect->height = MAX(rect->height, dy) + 1;
} else {
rect->height = (int)rect->height - dy + 1;
rect->y = y;
}
rect->x -= pw->paint.lineWidth;
rect->y -= pw->paint.lineWidth;
rect->width += pw->paint.lineWidth * 2;
rect->height+= pw->paint.lineWidth * 2;
}
void PwUndoSetRectangle(Widget w, XRectangle *rect)
{
PaintWidget pw = GET_PW(w);
if (pw->paint.undo == NULL)
return;
pw->paint.undo->box = *rect;
}
void PwUndoAddRectangle(Widget w, XRectangle *rect)
{
PaintWidget pw = GET_PW(w);
if (pw->paint.undo == NULL)
return;
pw->paint.undo->box = *RectUnion(rect, &pw->paint.undo->box);
}
void UndoSetRectangle(Widget w, XRectangle *rect)
{
PaintWidget pw = GET_PW(w);
if (pw->paint.undo == NULL)
return;
PwUndoSetRectangle(w, rect);
pw->paint.undo->box.x -= pw->paint.lineWidth;
pw->paint.undo->box.y -= pw->paint.lineWidth;
pw->paint.undo->box.width += pw->paint.lineWidth * 2 + 1;
pw->paint.undo->box.height+= pw->paint.lineWidth * 2 + 1;
}
void UndoStartRectangle(Widget w, OpInfo *info, XRectangle *rect)
{
UndoStart(w, info);
UndoSetRectangle(w, rect);
}